#include "PlayerCLass.h"
#include "HUDManager.h"
#include <math.h>

Vector3 PlayerClass::PLAYER_POSITION = Vector3(400, ((VoxelChunck::getYChunckSize() * TerrainClass::SCALE_TERRAIN) / 2 + 1), TerrainClass::START_TERRAIN_POSITION.z);
bool PlayerClass::GO_LEFT = false;
bool PlayerClass::GO_RIGHT = false;
bool PlayerClass::JUMP = false;
bool PlayerClass::Isfly = false;
bool PlayerClass::HAS_COLLIDED_FOR_OBJECTS = false;
bool PlayerClass::HAS_COLLIDED_WITH_TREE = false;
bool PlayerClass::HAS_COLLIDED_WITH_FLOOR = false;
bool PlayerClass::HAS_COLLIDED_WITH_WALL = false;
bool PlayerClass::HAS_FALLEN_OFF_TERRAIN = false;
Vector3 PlayerClass::VELOCITY_TERRAIN = Vector3(0, 0, 0);

PlayerClass::PlayerClass() {
	CubeRobot::CreateCube();

	controller = XBOXController(1);
	BuildRobotEntity();
	playerSubject = new Subject();
	amountHorizontalLinearVelocity = 0.001f;
	health = 100;

	isVelocityFalse = false;
	debug = false;

	flyTime = 0;
	rushTime = 0;
	JumpDelay = false;
	Invulnerable = 0.0f;
}

PlayerClass::~PlayerClass() {
	delete playerEntity;
}

void PlayerClass::UpdatePlayer(float msec) {
	/// ------ Added by Monica ------ //
	/*GO_LEFT = false;
	GO_RIGHT = false;
	JUMP = false;*/
	HAS_COLLIDED_WITH_TREE = false;
	HAS_COLLIDED_WITH_FLOOR = false;
	HAS_COLLIDED_WITH_WALL = false;
	TerrainClass::HAS_COLLIDED_WITH_TERRAIN = false;

	Vector3 posPlayer = physicsNodePlayer->GetPosition();

	//if (posPlayer.y < 0.0f) {
	//	physicsNodePlayer->SetPosition(Vector3(posPlayer.x, 0.0f, posPlayer.z));
		//
	//}
	/// ----------------------------- ///

	//// --------- Added by Monica --------------------------------//
	if (!HAS_FALLEN_OFF_TERRAIN) {
		if (posPlayer.y < 0.0f)
		{
			physicsNodePlayer->SetPosition(Vector3(posPlayer.x, 0.0f, posPlayer.z));
		}
		detectAndResolveCollisionsWithTerrain();
	}
	else
	{
		if (posPlayer.y < -500.f)
		{
			HUDManager::GetInstance()->SwitchToGameOver();
			physicsNodePlayer->SetPosition(Vector3(posPlayer.x, -500.0f, posPlayer.z));
		}		
	}

	//// ---------------------------------------------------------------- //

	////######### DEBUG ###########
	//if (Window::GetKeyboard()->KeyDown(KEYBOARD_T))	{
	//	debug = !debug;
	//}
	////###############################

	//----------------Jump Delay and Invunerablity-----------------//

	/*if (!JUMP && JumpDelay > 0.0f)
	 {
		 JumpDelay -= msec / 1000;
	}*/
	if (Invulnerable > 0.0f)
	{
		Invulnerable -= msec / 1000;
	}


	if (HAS_COLLIDED_WITH_FLOOR && JUMP == true)
	{
		JUMP = false;
		HAS_COLLIDED_FOR_OBJECTS = false;
		isVelocityFalse = false;
		debug = false;
	}

	if (HAS_COLLIDED_WITH_WALL)
	{
		TotalIncreaseValueofTerrain = 0.0f;
		Debuff();
	}

	// ------------- player movement / animation --------------- //

	//Detect the robot animation. J-LeftTurn, L-RightTurn, I-Rum, L-Stand, G-Jump
	if (Window::GetKeyboard()->KeyRelease(PLAYER_TURN_LEFT) || Window::GetKeyboard()->KeyRelease(PLAYER_TURN_RIGHT))
	{
		StopAnimation(playerEntity);
		//physicsNodePlayer->SetLinearVelocity(Vector3());
	}

	//if (!Window::GetKeyboard()->KeyHeld(PLAYER_TURN_LEFT) && !Window::GetKeyboard()->KeyHeld(PLAYER_TURN_RIGHT))
	//{
	//	StopAnimation(playerEntity);
	//	//physicsNodePlayer->SetLinearVelocity(Vector3());
	//}
	if (Window::GetKeyboard()->KeyDown(PLAYER_TURN_LEFT) && Window::GetKeyboard()->KeyHeld(PLAYER_TURN_LEFT) || (controller.GetState().Gamepad.sThumbLX < -6553))
	{
		//cout << "Leftturn" << endl;
		RobotAnimation('J', playerEntity);
		GO_LEFT = true;

	}

	if (Window::GetKeyboard()->KeyDown(PLAYER_TURN_RIGHT) && Window::GetKeyboard()->KeyHeld(PLAYER_TURN_RIGHT) || (controller.GetState().Gamepad.sThumbLX >  6553))
	{
		RobotAnimation('L', playerEntity);
		GO_RIGHT = true;
	}
	if (Window::GetKeyboard()->KeyDown(PLAYER_JUMP) && !Window::GetKeyboard()->KeyHeld(PLAYER_JUMP))
	{

		if (JUMP == false && !JumpDelay)
		{
			RobotAnimation('G', playerEntity);
			/*renderNodePlayer->RobotStand();
			renderNodePlayer->StateTransfer(JUMP);*/
		}

	}
	if (Window::GetKeyboard()->KeyDown(PLAYER_RUSH) && !Window::GetKeyboard()->KeyHeld(PLAYER_RUSH))
	{
		if (rushRelease&&!renderNodePlayer->getState(FLY))
		{
			renderNodePlayer->RobotStand();
			renderNodePlayer->StateTransfer(RUSH);
			Isrush = true;
			energy = 50;
		}
	}
	if (Window::GetKeyboard()->KeyDown(PLAYER_FLY) && !Window::GetKeyboard()->KeyHeld(PLAYER_FLY))
	{
		if (flyRelease)
		{
			renderNodePlayer->RobotStand();
			renderNodePlayer->StateTransfer(FLY);
			Fly(physicsNodePlayer);
			energy = 0;
		}

	}
	if (Isfly)
	{
		Vector3 position = physicsNodePlayer->GetPosition();
		if (position.y > terrain->getMaxHeightTerrain()) {
			position.y = terrain->getMaxHeightTerrain() + 50.0f;
			physicsNodePlayer->SetPosition(position);
		}
		if (flyTime<MAX_FLY_TIME)
		{
			flyTime++;
			TerrainClass::LINEAR_VELOCITY_Z += RUSH_VELOCITY_INCREASE;
		}
		else
		{
			physicsNodePlayer->SetUseGravity(true);
			Isfly = false;
			flyTime = 0;
		}
	}
	if (Window::GetKeyboard()->KeyDown(KEYBOARD_K) && Window::GetKeyboard()->KeyHeld(KEYBOARD_K))
	{
		RobotAnimation('K', playerEntity);
	}
	if (Window::GetKeyboard()->KeyDown(PLAYER_MOVE_BACKWARD) && Window::GetKeyboard()->KeyHeld(PLAYER_MOVE_BACKWARD))
	{
		RobotAnimation('O', playerEntity);
	}
	//if (Window::GetKeyboard()->KeyDown(PLAYER_MOVE_M) && Window::GetKeyboard()->KeyHeld(PLAYER_MOVE_M))
	//{
	//	RobotAnimation('M', playerEntity);
	//}
	//if (Window::GetKeyboard()->KeyDown(PLAYER_MOVE_N) && Window::GetKeyboard()->KeyHeld(PLAYER_MOVE_N))
	//{
	//	RobotAnimation('N', playerEntity);
	//}
	// -------------------------------------------------------- //

	if (Isrush)
	{
		rushTime++;
		if (rushTime<MAX_RUSH_TIME)
		{
			TerrainClass::LINEAR_VELOCITY_Z += RUSH_VELOCITY_INCREASE;
			//Renderer::GetRenderer().SetIsblur(true);
		}
		else
		{
			rushTime = 0;
			/*terrain->SetLinearVelocityZ(-0.3f);*/
			//TerrainClass::LINEAR_VELOCITY_Z = tempVelocity;
			Isrush = false;
			renderNodePlayer->StateTransfer(RUN);
			//Renderer::GetRenderer().SetIsblur(false);
		}
	}
	//if (Isrush)
	//{
	//	rushTime++;
	//	if (rushTime<MAX_RUSH_TIME)
	//	{
	//		TerrainClass::LINEAR_VELOCITY_Z += RUSH_VELOCITY_INCREASE;
	//		//Renderer::GetRenderer().SetIsblur(true);
	//	}
	//	else
	//	{
	//		rushTime = 0;
	//		/*terrain->SetLinearVelocityZ(-0.3f);*/
	//		//TerrainClass::LINEAR_VELOCITY_Z = RUSH_VELOCITY_INCREASE;
	//		Isrush = false;
	//		renderNodePlayer->StateTransfer(RUN);
	//		//Renderer::GetRenderer().SetIsblur(false);
	//	}
	//}

	if (renderNodePlayer->checkRunActive())
	{
		TotalIncreaseValueofTerrain += AMOUNT_INCREASE_WITHTIME_PASSING;
		//TerrainClass::LINEAR_VELOCITY_Z += AMOUNT_INCREASE_WITHTIME_PASSING;
	}

	//added by Matrix
	 //change the position and angle of camera based on player animation
	Vector3 position = physicsNodePlayer->GetPosition();
	if (Isfly)
	{
		Renderer::GetRenderer().GetCamera()->SetPosition(Vector3(position.x - 100.f, position.y + 400.f, position.z - 1000.f));
		/*	Renderer::GetRenderer().GetCamera()->SetPitch(-5.0f);
		Renderer::GetRenderer().GetCamera()->SetYaw(180);*/
	}
	else
	{
		Renderer::GetRenderer().GetCamera()->SetPosition(Vector3(position.x, position.y + 300.f, position.z - 800.f));
		/*Renderer::GetRenderer().GetCamera()->SetPitch(-5.0f);
		Renderer::GetRenderer().GetCamera()->SetYaw(180);*/
	}
	//added by Matrix
	//To check whether player collides with terrain or not
	if (Renderer::GetRenderer().GetIsFog())
	{
		energy = 101;
	}
	if (!TerrainClass::HAS_COLLIDED_WITH_TERRAIN)
	{
		
		//energy > 100 ? 100 : (energy+0.1);
		if (energy>100)
		{
			energy = 101;
			HUDManager::GetInstance()->getEnergyBar()->SetColour(Vector4(0, 0, 1, 1));
			rushRelease = true;
			flyRelease = true;
		}
		else
		{
			energy += 0.08;
			rushRelease = false;
			flyRelease = false;
			HUDManager::GetInstance()->getEnergyBar()->SetColour(Vector4(1, 0.5, 0, 1));
		}
	}

	Renderer::GetRenderer().SetPlayerVelocity(TerrainClass::LINEAR_VELOCITY_Z);
	Renderer::GetRenderer().SetExplosionPosition(position);
}

void PlayerClass::resetTerrainVelocity() {
	//reset the velocity of the terrain when the player has collided with an object and then moved
		if (GO_RIGHT || GO_LEFT || JUMP || Isfly) {
		GO_LEFT = false;
		GO_RIGHT = false;
		JUMP = false;

			isVelocityFalse = false;
			terrain->ResetTerrainVelocityAfterCollision();
		//terrain->resetVelocityOfPuddleCHunck(TerrainClass::LINEAR_VELOCITY_TERRAIN);
			HAS_COLLIDED_FOR_OBJECTS = false;
		}
	}

void PlayerClass::positionPlayerOnTerrain() {
	Vector3 oldPositionPlayer = physicsNodePlayer->GetPosition();
	float scale = TerrainClass::SCALE_TERRAIN;
	if (oldPositionPlayer.y < ((scale / 2) + 1)) {
		oldPositionPlayer.y = ((scale / 2) + 1);
		physicsNodePlayer->SetPosition(oldPositionPlayer);
	}
}

Vector3 PlayerClass::updatePlayersMovementOnTerrain() {
	//update the players position with how much the terrain has moved since last time
	Vector3 playerPosition = physicsNodePlayer->GetPosition();
	amountMovementZ = terrain->GetAmountMovementOnZAxis();

	//add the z movement of the terrain
	playerPosition.z -= amountMovementZ;
	return playerPosition;
	}

bool PlayerClass::checkAndResolvePlayerCollisionOnYAxis(Vector3 playerPosition, Vector3 position, Vector3 velocity) {
		Vector3 transformCoord = getPlayerCoordinatesFromVoxel(false, false);

	if (round(playerPosition.y) >= round(transformCoord.y)) {
			position.y = transformCoord.y + 26.0f;

			physicsNodePlayer->SetPosition(position);
			physicsNodePlayer->SetLinearVelocity(Vector3(velocity.x, 0, velocity.z));

			playerPosition = physicsNodePlayer->GetPosition();
			playerPosition.z -= amountMovementZ;

			JumpDelay = false;
			return setPlayerVoxelCoordinates(playerPosition);
		}
	return true;
	}

bool PlayerClass::checkAndResolvePlayerCollisionOnXAxisLeft(Vector3 playerPosition, Vector3 position, Vector3 velocity) {
	Vector3 transformCoord = getPlayerCoordinatesFromVoxel(false, false);

	if ((round(playerPosition.x) > (transformCoord.x + 25.0f))) {
		Vector3 normal = playerPosition - transformCoord;
		//get the distance squared
		float distSq = Vector3::Dot(normal, normal);
		//calculate the distance between the origins of the 2 objects
		float distance = 5.0f + 25.0f;
		//calculate penetration depth
		float penetration = distance - sqrtf(distSq);

		position.x += abs(penetration);
		//position.x = transformCoord.x + 30.0f;

		physicsNodePlayer->SetLinearVelocity(Vector3(0, velocity.y, velocity.z));
		physicsNodePlayer->SetPosition(position);

		playerPosition = physicsNodePlayer->GetPosition();
		playerPosition.z -= amountMovementZ;

			HAS_COLLIDED_WITH_FLOOR = true;
		return setPlayerVoxelCoordinates(playerPosition);
	}
	return true;
}

bool PlayerClass::checkAndResolvePlayerCollisionOnXAxisRight(Vector3 playerPosition, Vector3 position, Vector3 velocity) {
	Vector3 transformCoord = getPlayerCoordinatesFromVoxel(false, false);

	if ((round(playerPosition.x) < (transformCoord.x - 25.0f))) {
			Vector3 normal = playerPosition - transformCoord;
			//get the distance squared
			float distSq = Vector3::Dot(normal, normal);
			//calculate the distance between the origins of the 2 objects
			float distance = 5.0f + 25.0f;
			//calculate penetration depth
			float penetration = distance - sqrtf(distSq);

			//offset it a little so that the collision does not happen that often
			position.x -= abs(penetration);

			physicsNodePlayer->SetPosition(position);
			physicsNodePlayer->SetLinearVelocity(Vector3(0, velocity.y, velocity.z));

			playerPosition = physicsNodePlayer->GetPosition();
			playerPosition.z -= amountMovementZ;

			return setPlayerVoxelCoordinates(playerPosition);
	}
	return true;
}

void PlayerClass::checkAndResolvePlayerCollisionOnZAxis(Vector3 playerPosition, Vector3 terrainPosition) {
	Vector3 transformCoord = getPlayerCoordinatesFromVoxel(false, false);

	if ((round(playerPosition.z) <= (transformCoord.z))) {
		Vector3 normal = playerPosition - transformCoord;
		//get the distance squared
		float distSq = Vector3::Dot(normal, normal);
		//calculate the distance between the origins of the 2 objects
		float distance = 5.0f + 27.0f;
		//calculate penetration depth
		float penetration = distance - sqrtf(distSq);

		if (penetration > 0.0f) {
			penetration = -10.0f;
		}

		terrainPosition.z -= (penetration);
		terrain->SetMovementTerrain(terrainPosition);
		isVelocityFalse = true;
		amountMovementZ = amountMovementZ - (penetration);
		terrain->SetAmountMovementz(amountMovementZ);

		HAS_COLLIDED_FOR_OBJECTS = true;
		//terrain->resetVelocityOfPuddleCHunck(TerrainClass::LINEAR_VELOCITY_TERRAIN);
	}
}

void PlayerClass::detectAndResolveCollisionsWithTerrain() {
	//// ------------- Collision detection with terrain ------------------ //
	resetTerrainVelocity();
	Vector3 playerPosition = updatePlayersMovementOnTerrain();

	bool value = setPlayerVoxelCoordinates(playerPosition);

	//check to see if the player is within the bounds of the terrain
	checkPlayerOnTerrainBounds(playerPosition);

	Vector3 terrPos_00 = terrain->GetTerrainPositionAt(0);
	Vector3 position = physicsNodePlayer->GetPosition();
	Vector3 velocity = physicsNodePlayer->GetLinearVelocity();

	//######### DEBUG ###########
	if (Window::GetKeyboard()->KeyDown(PLAYER_DEBUG))	{
		debug = !debug;
	}
	//###############################

	//get the type of the block that the player is on and change the velocity accordingly
	BlockType bType = terrain->getBlockTypeAt(playerCoordinatesVoxel);
	switch (bType) {
		case BlockType_Bare: {
			TerrainClass::LINEAR_VELOCITY_Z = LINEAR_VELOCITY_BARE_GROUND + TotalIncreaseValueofTerrain;
			break;
		}
		case BlockType_Rock: {
			TerrainClass::LINEAR_VELOCITY_Z = LINEAR_VELOCITY_ROCK + TotalIncreaseValueofTerrain;
			break;
		}
		case BlockType_Sand: {
			TerrainClass::LINEAR_VELOCITY_Z = LINEAR_VELOCITY_SAND + TotalIncreaseValueofTerrain;
			break;
		}
		default: {
			TerrainClass::LINEAR_VELOCITY_Z = LINEAR_VELOCITY_GRASS + TotalIncreaseValueofTerrain;
			break;
		}
	}


	if (TerrainClass::LINEAR_VELOCITY_Z < MAX_VELOCITY)
	{
		TerrainClass::LINEAR_VELOCITY_Z = MAX_VELOCITY;
	}


	////the actual collision detection
	////check the collision with objects coming from ahead
	if (value == true) {
		TerrainClass::HAS_COLLIDED_WITH_TERRAIN = true;
		value = checkAndResolvePlayerCollisionOnYAxis(playerPosition, position, velocity);

		if (value == false)
		{
			HAS_COLLIDED_WITH_FLOOR = true;
		}
	}

	if (value == true) {
		TerrainClass::HAS_COLLIDED_WITH_TERRAIN = true;
		value = checkAndResolvePlayerCollisionOnXAxisLeft(playerPosition, position, velocity);
	}

	if (value == true) {
		TerrainClass::HAS_COLLIDED_WITH_TERRAIN = true;
		value = checkAndResolvePlayerCollisionOnXAxisRight(playerPosition, position, velocity);
	}

	if (value == true) {
		TerrainClass::HAS_COLLIDED_WITH_TERRAIN = true;
		checkAndResolvePlayerCollisionOnZAxis(playerPosition, terrPos_00);

		if (value == true)
		{
			HAS_COLLIDED_WITH_WALL = true;
		}
	}
}

void PlayerClass::resetPlayerOnTerrain(Vector3 position, float scale) {
	//get the height of the terrain at the position of the player and respawn it on the terrain with the coorect height
	float height = terrain->getHeightAtPosition(Vector3((VoxelChunck::getXChunckSize() - 1) * scale / 2, position.y, position.z));
	physicsNodePlayer->SetPosition(Vector3((VoxelChunck::getXChunckSize() - 1) * scale / 2, height, 0.0f));
	//reset the velocity of the player
	physicsNodePlayer->SetLinearVelocity(Vector3(0, 0, 0));
}

void PlayerClass::checkPlayerOnTerrainBounds(Vector3 position) {
	Vector3 playerPos = physicsNodePlayer->GetPosition();
	float scale = TerrainClass::SCALE_TERRAIN;
	if (playerPos.x >(VoxelChunck::getXChunckSize() - 1) * scale || playerPos.x < 0) {
		//resetPlayerOnTerrain(position, scale);
		makePlayerFallOffTerrain();
	}

	//for the y axis so that the player does not get outside the range
	if (playerPos.y >(VoxelChunck::getYChunckSize() - 2) * scale) {
		physicsNodePlayer->SetPosition(Vector3(playerPos.x, (VoxelChunck::getYChunckSize() - 2) * scale, playerPos.z));
	}
}

void PlayerClass::makePlayerFallOffTerrain() {
	//make the player stop the update
	HAS_FALLEN_OFF_TERRAIN = true;

	//apply gravity to player
	physicsNodePlayer->SetUseGravity(true);
}


void PlayerClass::BuildRobotEntity() {
	renderNodePlayer = new CubeRobot();
	//sNode->SetModelScale(Vector3(TerrainClass::SCALE_TERRAIN / 2, TerrainClass::SCALE_TERRAIN / 2, TerrainClass::SCALE_TERRAIN / 2));
	//renderNodePlayer->SetModelScale(Vector3(1, 1, 1));
	renderNodePlayer->SetTransform(Matrix4::Translation(PLAYER_POSITION));
	renderNodePlayer->SetModelScale(Vector3(30, 40, 30));
	
	physicsNodePlayer = new PhysicsNode();
	physicsNodePlayer->SetPosition(PLAYER_POSITION);

	physicsNodePlayer->SetUseGravity(true);
	physicsNodePlayer->SetCollisionVolume(new CollisionOBB(Vector3(5, 5, 5), PLAYER));

	playerEntity = new GameEntity(renderNodePlayer, physicsNodePlayer);
	//do not add the player physics node to the physics system 
	//we need a separate update function for the player
	playerEntity->SetConnectToPhysicsSystem(true);
	//this will only add the scene node and will set the target for scene node and physics node
	playerEntity->ConnectToSystems();


	SpringNode* spNode = new SpringNode();
	SpringMesh* spMesh = SpringMesh::GenerateSpringMesh();
	spNode->SetModelScale(Vector3(20, 20, 20));
	spNode->SetTransform(Matrix4::Translation(Vector3(0, 0, 0)));
	spNode->SetMesh(spMesh);
	spNode->SetColour(Vector4(2, 0, 0, 1));
	spMesh->SetTarget(spNode);
	renderNodePlayer->GetBody()->AddChild(spNode);
	PhysicsSystem::GetPhysicsSystem().AddConstraint(spMesh);
}

void PlayerClass::RobotAnimation(char Move, GameEntity* robot){
	switch (Move)
	{
	case'J':
	{
		LeftTurn(robot);
		break;
	}
	case'G':
	{
		Jump(robot);

		JUMP = true;
		flyTime = 0;
		Isfly = false;
		JumpDelay = true;
		physicsNodePlayer->SetUseGravity(true);
		break;
	}
	case'L':
	{
		RightTurn(robot);
		break;
	}
	case 'K': {
		StraightAhead(robot);
		break;
	}
	case 'O': {
		MoveUp(robot);
		break;
	}
	case 'M': {
		MoveDown(robot);
		break;
	}
	case 'N': {
		MoveBack(robot);
		break;
	}
	default:
		break;
	}
}

void PlayerClass::LeftTurn(GameEntity* robot) {
	robot->GetPhysicsNode().AddAcceleration(Vector3(amountHorizontalLinearVelocity, 0, 0));
	//robot->GetPhysicsNode().SetLinearVelocity(Vector3(amountHorizontalLinearVelocity, 0, 0));
}

void PlayerClass::RightTurn(GameEntity* robot) {
	robot->GetPhysicsNode().AddAcceleration(Vector3(-amountHorizontalLinearVelocity, 0, 0));
	//robot->GetPhysicsNode().SetLinearVelocity(Vector3(-amountHorizontalLinearVelocity, 0, 0));
}

void PlayerClass::Jump(GameEntity* robot) {
	robot->GetPhysicsNode().SetLinearVelocity(Vector3(0, 2, 0));
}

void PlayerClass::StopAnimation(GameEntity* robot){
	robot->GetPhysicsNode().AccelerationToZero();
	/*Vector3 velocity = robot->GetPhysicsNode().GetLinearVelocity();
	velocity.x = 0;
	robot->GetPhysicsNode().SetLinearVelocity(velocity);*/
}

void PlayerClass::StraightAhead(GameEntity* robot) {
	robot->GetPhysicsNode().SetLinearVelocity(Vector3(0, 0, 0.1));
}

void PlayerClass::MoveUp(GameEntity* robot) {
	robot->GetPhysicsNode().SetLinearVelocity(Vector3(0, 0.1, 0));
}

void PlayerClass::MoveDown(GameEntity* robot) {
	robot->GetPhysicsNode().SetLinearVelocity(Vector3(0, -0.1, 0));
}

void PlayerClass::MoveBack(GameEntity* robot) {
	robot->GetPhysicsNode().SetLinearVelocity(Vector3(0, 0, -0.1));
}

void PlayerClass::Buff()
{
	health += 10;

	if (health > 100)
	{
		health = 100;
	} 

	GameSound::GetInstance()->InsertSound(3,false);
}

void PlayerClass::Debuff()
{
	if (Invulnerable <= 0.0f)
	{
		//amount of health lost is equal to current speed shared by minimum speed
		//times by lowest amount of health a player can lose.
		health -= (TerrainClass::LINEAR_VELOCITY_Z / TerrainClass::LINEAR_VELOCITY_Z) * 10.0f;
		health < 0 ? 0 : health;
		Invulnerable = INVUNERABILITY_TIME;
	}
}

/// -------- Added by Monica ------ //
bool PlayerClass::setPlayerVoxelCoordinates(Vector3 position) {
	float scale = TerrainClass::SCALE_TERRAIN;
	//for the robot the offset will be on the x axis +- 40
	Vector3 posXPositive = ChunckManager::transformWorldCoordinatesToVoxelCoordinates(position, scale, 10, 0, 0);
	Vector3 posXNegative = ChunckManager::transformWorldCoordinatesToVoxelCoordinates(position, scale, -10, 0, 0);

	if (posXPositive.z >= 50) {
		posXPositive.z = 49;
	}
	if (posXNegative.z >= 50) {
		posXNegative.z = 49;
	}

	if (terrain->GetActiveVoxel(posXPositive)) {
		//set the player voxel coordinates
		playerCoordinatesVoxel = posXPositive;
		return true;
	}
	if (terrain->GetActiveVoxel(posXNegative)) {
		//set the player voxel coordinates
		playerCoordinatesVoxel = posXNegative;
		return true;
	}
	return false;
}

Vector3 PlayerClass::getPlayerCoordinatesFromVoxel(bool left, bool right) {
	float scale = TerrainClass::SCALE_TERRAIN;
	if (left) {
		return ChunckManager::transformVoxelCoordinatesToWorldCoordinates(playerCoordinatesVoxel, scale, -10, 0, 0);
	}
	if (right) {
		return ChunckManager::transformVoxelCoordinatesToWorldCoordinates(playerCoordinatesVoxel, scale, 10, 0, 0);
	}
	return ChunckManager::transformVoxelCoordinatesToWorldCoordinates(playerCoordinatesVoxel, scale, 0, 0, 0);
}
/// ------------------------------------- ///

void PlayerClass::SetStateInCubeRobot(int state){
	switch (state)
	{
	case FLY:
		renderNodePlayer->RobotStand();
		renderNodePlayer->StateTransfer(FLY);
		//animation->Fly(physicsNodePlayer);
		Fly(physicsNodePlayer);
		break;
	case RUSH:
		renderNodePlayer->RobotStand();
		renderNodePlayer->StateTransfer(RUSH);
		SetSceneRush(true);
		break;
	default:
		break;
	}
}
void PlayerClass::Fly(PhysicsNode* player){
	animation->Fly(physicsNodePlayer);
	physicsNodePlayer->SetUseGravity(false);
	Isfly = true;
}
void PlayerClass::Reset()
{
	physicsNodePlayer->SetPosition(PLAYER_POSITION);
	TerrainClass::RESTART_TERRAIN = false;
	
	health = 100;
	GO_LEFT = false;
	GO_RIGHT = false;
	JUMP = false;
	isVelocityFalse = false;
	debug = false;
	
	amountHorizontalLinearVelocity = 0.001f;
	isVelocityFalse = false;
	debug = false;
	JumpDelay = false;
	Invulnerable = 0.0f;
	flyTime = 0;
	rushTime = 0;

	HAS_FALLEN_OFF_TERRAIN = false;
	HAS_COLLIDED_FOR_OBJECTS = false;


	physicsNodePlayer->SetLinearVelocity(Vector3(0,0,0));

}